Workflow automation/AzureSiteRecovery-RansomwareProtection/RansomwareDetector.ps1 (216 lines of code) (raw):
param (
[parameter(Mandatory=$true)]
[Object]$RecoveryPlanContext,
[parameter(Mandatory=$true)]
[Object]$VaultId,
[parameter(Mandatory=$true)]
[Object]$ChangePit
)
# ToDo: Alerts detection conditions need to update.
<#
.SYNOPSIS
Waits for ASR job completion
#>
Function WaitForJobCompletion {
param(
[parameter(Mandatory = $True)] [string] $JobId,
[int] $JobQueryWaitTimeInSeconds = 30
)
$isJobLeftForProcessing = $true
Write-Output "Job - $JobId is in-Progress"
do {
$azJob = Get-AzRecoveryServicesAsrJob -Name $JobId
$azJob
if ($azJob.State -eq "InProgress" -or $azJob.State -eq "NotStarted") {
$isJobLeftForProcessing = $true
}
else {
$isJobLeftForProcessing = $false
}
if ($isJobLeftForProcessing) {
$azJob
Start-Sleep -Seconds $JobQueryWaitTimeInSeconds
}
else {
if ($null -eq $azJob.DisplayName -or $azJob.DisplayName -eq '') {
$messageToDisplay = "NA"
}
else {
$messageToDisplay = $azJob.DisplayName
}
if ($azJob.State -eq "Failed") {
$azJob
$errorMessage = ($azJob.Errors.ServiceErrorDetails | ConvertTo-json -Depth 1)
throw $errorMessage
}
else {
$azJob
}
}
}While ($isJobLeftForProcessing)
}
<#
.SYNOPSIS
Triggers ASR Change Recovery Point operation.
#>
Function ChangeRecoveryPoint {
param(
[parameter(Mandatory = $True)] [string] $VmIdentifier,
[parameter(Mandatory = $True)] [string] $DetectionTime
)
Write-Output "Getting the VmIdentifier"
$VmIdentifier
Write-Output "Getting the vault"
$VaultId
$resource = Get-AzResource -ResourceId $VaultId
$vault = Get-AzRecoveryServicesVault -ResourceGroupName $resource.ResourceGroupName -Name $resource.Name
Set-AzRecoveryServicesAsrVaultContext -Vault $vault
$fabrics = Get-AzRecoveryServicesAsrFabric
if ($null -ne $fabrics) {
foreach ($fabric in $fabrics) {
$containers = Get-AzRecoveryServicesAsrProtectionContainer -Fabric $fabric
foreach ($container in $containers) {
$protectedItems = Get-AzRecoveryServicesAsrReplicationProtectedItem -ProtectionContainer $container
foreach ($protectedItem in $protectedItems) {
$rpi = Get-AzRecoveryServicesAsrReplicationProtectedItem -ProtectionContainer $container -Name $protectedItem.Name
# Identifying the Replicated item using Azure VM Id in ASR.
if (($rpi.ProviderSpecificDetails.LifecycleId -eq $VmIdentifier) -or # Azure to Azure scenario.
($rpi.ProviderSpecificDetails.internalIdentifier -eq $VmIdentifier)) #VMware to Azure scenario.
{
#Replicated item found for Failed over azure VM.
Write-Output "Protected item found."
$rpi
#get recovery points
$recoveryPoints = Get-AzRecoveryServicesAsrRecoveryPoint -ReplicationProtectedItem $protectedItem | Sort-Object RecoveryPointTime -Descending
$recoveryPoints
# Going to back to the Recovery point older then detection time.
$ChangeRP = $recoveryPoints | Where-Object{ $_.RecoveryPointTime -le $DetectionTime} | Select-Object -First 1
Write-Output "Changing the recovery point."
$ChangeRP
if (($ChangeRP -ne $null) -and ($ChangePit -eq $True))
{
#Retry the failover with new recovery point.
$asrJob = Start-AzRecoveryServicesAsrApplyRecoveryPoint -ReplicationProtectedItem $protectedItem -RecoveryPoint $ChangeRP
WaitForJobCompletion -JobId $asrJob.Name
}
break
}
}
}
}
}
}
# Recovery plan context, this value coming from the Recovery plan.
Write-Output $RecoveryPlanContext
Write-Output "checking variable"
$RecoveryPlanContextObj = ""
try
{
$RecoveryPlanContextObj = $RecoveryPlanContext | ConvertFrom-Json
}
catch {
$RecoveryPlanContextObj = $RecoveryPlanContext
Write-Output -Message $_.Exception
}
Write-Output "getting VM map object"
$VMMapColl = $RecoveryPlanContextObj.VmMap
Write-Output $VMMapColl
$SubscriptionId = ""
$ResourceGroupName = ""
$VMCollection = @()
if($VMMapColl -ne $null)
{
Write-Output "VMMapColl Variable is Not Null"
$VMinfo = $VMMapColl | Get-Member | Where-Object MemberType -EQ NoteProperty | select -ExpandProperty Name
#$vmMap = $RecoveryPlanContextObj.VmMap
Write-Output "VMinfo: $VMinfo"
foreach($VMID in $VMinfo)
{
$VM = $VMMapColl.$VMID
Write-Output $VM
if( !(($VM -eq $Null) -Or ($VM.ResourceGroupName -eq $Null) -Or ($VM.RoleName -eq $Null)))
{
$VM | Add-Member NoteProperty RecoveryPlanName $RecoveryPlanContextObj.RecoveryPlanName
$VM | Add-Member NoteProperty FailoverType $RecoveryPlanContextObj.FailoverType
$VM | Add-Member NoteProperty FailoverDirection $RecoveryPlanContextObj.FailoverDirection
$VM | Add-Member NoteProperty GroupId $RecoveryPlanContextObj.GroupId
$VM | Add-Member NoteProperty VMId $VMID
$VM | Add-Member NoteProperty VmRg $VM.ResourceGroupName
$VM | Add-Member NoteProperty VmName $VM.RoleName
$VMCollection += $VM
$SubscriptionId = $VM.SubscriptionId
$ResourceGroupName = $VM.ResourceGroupName
}
}
}
else
{
Write-Output "VMMapColl Variable is Null"
}
$CollectionCount = $VMCollection.Count
Write-Output "Collection Count: $CollectionCount"
#Returning Collection
Write-Output $VMCollection
if ($SubscriptionId -eq "")
{
Write-Output "SubscriptionId not found."
exit
}
Write-Output "SubscriptionId : $SubscriptionId"
try
{
"Logging in to Azure..."
Connect-AzAccount -Identity
}
catch {
Write-Error -Message $_.Exception
throw $_.Exception
}
Get-AzContext
Set-AzContext -SubscriptionId $SubscriptionId
foreach ($vmDetails in $VMCollection)
{
$azureVm = Get-AzVM -Name $vmDetails.VmName -ResourceGroupName $vmDetails.VmRg -ErrorAction SilentlyContinue
if ($null -ne $azureVm) {
Write-Output "Found Azure VM."
$azureVm.Name
}
else
{
Write-Output "Not found Azure VM."
$vmDetails.VmName
continue
}
$alertFound = $false
$alerts = Get-AzSecurityAlert -ResourceGroupName $azureVm.ResourceGroupName
foreach ($alert in $alerts)
{
try
{
Write-Output "Validating alert "
# alert filter – need to update the alert conditions.
if (($alert.ResourceIdentifiers.AzureResourceId -ne $null) -and
($alert.ResourceIdentifiers.AzureResourceId -ieq $azureVm.Id) -and
($alert.Severity -ieq "High")) #High, Medium, Low, Informational
{
Write-Output "Found alert for the VM"
$vmDetails.VmName
$alert
$alertFound = $true
#Change recovery point only if your VM wants to go back to old date.
ChangeRecoveryPoint -VmIdentifier $vmDetails.VMID -DetectionTime $alert.startTimeUtc
break
}
}
catch
{
Write-Error -Message $_.Exception
continue
}
}
if ($alertFound -eq $false)
{
Write-Output "No alerts found"
$vmDetails.VmName
}
}